{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Structured Outputs with Instructor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will show how to use [Instructor](https://python.useinstructor.com/) with [Gemini Flash](https://deepmind.google/technologies/gemini/flash/) to get structured outputs with a human in the loop.\n",
    "\n",
    "Suppose you have an outline for a course you're teaching and you want to break it down into n topics with this structure:  \n",
    "\n",
    "    Topic 1\n",
    "    |__ Subtopic 1\n",
    "        |__ Concept 1\n",
    "        |__ Concept 2\n",
    "        |   ...\n",
    "    |__ Subtopic 2\n",
    "        |__ Concept 1\n",
    "        |__ Concept 2\n",
    "        |__ Concept 3\n",
    "        |   ...\n",
    "    |   ...\n",
    "    Topic 2\n",
    "    |__ Subtopic 1\n",
    "        |__ Concept 1\n",
    "        |   ...\n",
    "    |   ...\n",
    "    .\n",
    "    .\n",
    "    .\n",
    "    Topic n\n",
    "    |__ Subtopic 1\n",
    "        |__ Concept 1\n",
    "        |   ...\n",
    "    |   ...\n",
    "    \n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Burr\n",
    "\n",
    "We _could_ just run a loop to generate a new topic `n` times, but what if we're not happy with topic `2/n`? What if the model comes up with a naming convention that we don't like and our prompt wasn't that specific in the first place? What if we just want to add some sutble changes to the latest generated topic?\n",
    "\n",
    "We just wasted all those tokens, minutes, dollars.\n",
    "\n",
    "That's where **Burr** comes in. By having the `creator` function as a node, we will ask the user for feedback on the generated topic. If the user is happy with the topic, we will move on to the next one. If not, we will use the feedback to generate the topic again. We will keep doing this until we've reached `n` topics that the user is happy with.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The autoreload extension is already loaded. To reload it, use:\n",
      "  %reload_ext autoreload\n"
     ]
    }
   ],
   "source": [
    "from application import Subtopic, Topic, creation_template, topics_system_template\n",
    "from application import application as topics_application\n",
    "\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "%reload_ext autoreload"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Models"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll first need to create our Pydantic models to define the structure. Let's use some dummy data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'Operations',\n",
       " 'subtopics': [{'name': 'Addition',\n",
       "   'concepts': ['Addition Of Two Numbers',\n",
       "    'Addition Of Negative Numbers',\n",
       "    'Addition Of One Negative And One Positive Number']},\n",
       "  {'name': 'Subtraction',\n",
       "   'concepts': ['Subtraction Of Two Numbers',\n",
       "    'Subtrcting A Larger Number From A Smaller Number']},\n",
       "  {'name': 'Multiplication',\n",
       "   'concepts': ['Multiplication Of Two Numbers',\n",
       "    'Multiplication Of Negative Numbers']},\n",
       "  {'name': 'Division',\n",
       "   'concepts': ['Division Of Two Numbers', 'Division Of A Number By Zero']}]}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "topic_name = \"Operations\"\n",
    "subtopic_names = [\"Addition\", \"Subtraction\", \"Multiplication\", \"Division\"]\n",
    "subtopic_concepts = [\n",
    "    [\n",
    "        \"Addition of two numbers\",\n",
    "        \"Addition of negative numbers\",\n",
    "        \"Addition of one negative and one positive number\",\n",
    "    ],\n",
    "    [\"Subtraction of two numbers\", \"Subtrcting a larger number from a smaller number\"],\n",
    "    [\"Multiplication of two numbers\", \"Multiplication of negative numbers\"],\n",
    "    [\"Division of two numbers\", \"Division of a number by zero\"],\n",
    "]\n",
    "subtopics = [\n",
    "    Subtopic(name=subtopic_name, concepts=concepts)\n",
    "    for subtopic_name, concepts in zip(subtopic_names, subtopic_concepts)\n",
    "]\n",
    "topic = Topic(name=topic_name, subtopics=subtopics)\n",
    "topic.model_dump()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Instructor allows us to set `Topic` as the return type of our LLM call. So we can guarantee that the output will be a `Topic` object, and not just a string."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Let's just see how our prompts will look"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### System Prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"You are a world class course instructor.\"\n",
      "You'll be given a course outline and you have to generate 3 topics.\n",
      "For each topic:\n",
      "    1. Generate a 3-5 word topic name that encapsulates the description.\n",
      "    2. Generate 2-4 subtopics for the topic. Also 3-5 words each.\n",
      "    For each subtopic:\n",
      "        Generate 2-4 concepts. Also 3-5 words each. The concepts should be related to the subtopic.\n",
      "        Think of concepts as the smallest unit of knowledge that can be taught from the subtopic. And add a verb to the concept to make it actionable.\n",
      "        For example:\n",
      "            \"Calculate Derivatives\" instead of \"Derivatives\".\n",
      "            \"Identify Finite Sets\" instead of \"Finite Sets\".\n",
      "            \"Find the y-intercept\" instead of \"y-intercept\".\n",
      "    The subtopics and concepts should be in the correct order.\n"
     ]
    }
   ],
   "source": [
    "print(topics_system_template(num_required_topics=3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### User Prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<outline>\n",
      "history, science, math\n",
      "</outline>\n",
      "\n",
      "<num_required_topics>\n",
      "3\n",
      "</num_required_topics>\n",
      "\n",
      "<topics_so_far>\n",
      "1/3\n",
      "TOPIC: Math\n",
      "SUBTOPIC 1: Algebra\n",
      "CONCEPT 1: Equations\n",
      "CONCEPT 2: Inequalities\n",
      "SUBTOPIC 2: Geometry\n",
      "CONCEPT 1: Angles\n",
      "CONCEPT 2: Area\n",
      "\n",
      "2/3\n",
      "TOPIC: Science\n",
      "SUBTOPIC 1: Biology\n",
      "CONCEPT 1: Cells\n",
      "CONCEPT 2: Dna\n",
      "SUBTOPIC 2: Physics\n",
      "CONCEPT 1: Energy\n",
      "CONCEPT 2: Forces\n",
      "</topics_so_far>\n",
      "\n",
      "Generate the next topic.\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    creation_template(\n",
    "        outline=\"history, science, math\",\n",
    "        topics_so_far=[\n",
    "            Topic(\n",
    "                name=\"Math\",\n",
    "                subtopics=[\n",
    "                    Subtopic(name=\"Algebra\", concepts=[\"Equations\", \"Inequalities\"]),\n",
    "                    Subtopic(name=\"Geometry\", concepts=[\"Angles\", \"Area\"]),\n",
    "                ],\n",
    "            ),\n",
    "            Topic(\n",
    "                name=\"Science\",\n",
    "                subtopics=[\n",
    "                    Subtopic(name=\"Biology\", concepts=[\"Cells\", \"DNA\"]),\n",
    "                    Subtopic(name=\"Physics\", concepts=[\"Energy\", \"Forces\"]),\n",
    "                ],\n",
    "            ),\n",
    "        ],\n",
    "        num_required_topics=3,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Application"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"503pt\" height=\"407pt\"\n",
       " viewBox=\"0.00 0.00 502.79 407.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 403)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-403 498.79,-403 498.79,4 -4,4\"/>\n",
       "<!-- setup -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>setup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M268.79,-332C268.79,-332 236.79,-332 236.79,-332 230.79,-332 224.79,-326 224.79,-320 224.79,-320 224.79,-308 224.79,-308 224.79,-302 230.79,-296 236.79,-296 236.79,-296 268.79,-296 268.79,-296 274.79,-296 280.79,-302 280.79,-308 280.79,-308 280.79,-320 280.79,-320 280.79,-326 274.79,-332 268.79,-332\"/>\n",
       "<text text-anchor=\"middle\" x=\"252.79\" y=\"-310.3\" font-family=\"Times,serif\" font-size=\"14.00\">setup</text>\n",
       "</g>\n",
       "<!-- creator -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>creator</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M157.79,-265C157.79,-265 113.79,-265 113.79,-265 107.79,-265 101.79,-259 101.79,-253 101.79,-253 101.79,-241 101.79,-241 101.79,-235 107.79,-229 113.79,-229 113.79,-229 157.79,-229 157.79,-229 163.79,-229 169.79,-235 169.79,-241 169.79,-241 169.79,-253 169.79,-253 169.79,-259 163.79,-265 157.79,-265\"/>\n",
       "<text text-anchor=\"middle\" x=\"135.79\" y=\"-243.3\" font-family=\"Times,serif\" font-size=\"14.00\">creator</text>\n",
       "</g>\n",
       "<!-- setup&#45;&gt;creator -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>setup&#45;&gt;creator</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M224.76,-297.43C209.93,-289.19 191.48,-278.94 175.22,-269.91\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"176.9,-266.84 166.46,-265.04 173.5,-272.96 176.9,-266.84\"/>\n",
       "</g>\n",
       "<!-- input__num_required_topics -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__num_required_topics</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" cx=\"137.79\" cy=\"-381\" rx=\"137.58\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"137.79\" y=\"-377.3\" font-family=\"Times,serif\" font-size=\"14.00\">input: num_required_topics</text>\n",
       "</g>\n",
       "<!-- input__num_required_topics&#45;&gt;setup -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__num_required_topics&#45;&gt;setup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M167.4,-363.26C182.09,-354.96 199.98,-344.85 215.58,-336.03\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"217.48,-338.98 224.46,-331.01 214.03,-332.88 217.48,-338.98\"/>\n",
       "</g>\n",
       "<!-- input__outline -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>input__outline</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" cx=\"366.79\" cy=\"-381\" rx=\"73.39\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"366.79\" y=\"-377.3\" font-family=\"Times,serif\" font-size=\"14.00\">input: outline</text>\n",
       "</g>\n",
       "<!-- input__outline&#45;&gt;setup -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__outline&#45;&gt;setup</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M339.19,-364.27C324.43,-355.85 306.04,-345.36 290.03,-336.23\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"291.34,-332.95 280.92,-331.04 287.88,-339.04 291.34,-332.95\"/>\n",
       "</g>\n",
       "<!-- creator&#45;&gt;creator -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>creator&#45;&gt;creator</title>\n",
       "<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M169.8,-252.99C179.91,-252.81 187.79,-250.81 187.79,-247 187.79,-244.62 184.71,-242.94 179.94,-241.98\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"180.08,-238.48 169.8,-241.01 179.42,-245.45 180.08,-238.48\"/>\n",
       "<text text-anchor=\"middle\" x=\"274.79\" y=\"-243.3\" font-family=\"Times,serif\" font-size=\"14.00\">generated_topic is None</text>\n",
       "</g>\n",
       "<!-- get_topic_feedback -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>get_topic_feedback</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M199.79,-198C199.79,-198 71.79,-198 71.79,-198 65.79,-198 59.79,-192 59.79,-186 59.79,-186 59.79,-174 59.79,-174 59.79,-168 65.79,-162 71.79,-162 71.79,-162 199.79,-162 199.79,-162 205.79,-162 211.79,-168 211.79,-174 211.79,-174 211.79,-186 211.79,-186 211.79,-192 205.79,-198 199.79,-198\"/>\n",
       "<text text-anchor=\"middle\" x=\"135.79\" y=\"-176.3\" font-family=\"Times,serif\" font-size=\"14.00\">get_topic_feedback</text>\n",
       "</g>\n",
       "<!-- creator&#45;&gt;get_topic_feedback -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>creator&#45;&gt;get_topic_feedback</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M129.76,-228.92C129.13,-222.7 128.91,-215.5 129.11,-208.6\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"132.63,-208.39 129.75,-198.19 125.64,-207.95 132.63,-208.39\"/>\n",
       "</g>\n",
       "<!-- input__attempts -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>input__attempts</title>\n",
       "<ellipse fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" cx=\"123.79\" cy=\"-314\" rx=\"83.39\" ry=\"18\"/>\n",
       "<text text-anchor=\"middle\" x=\"123.79\" y=\"-310.3\" font-family=\"Times,serif\" font-size=\"14.00\">input: attempts</text>\n",
       "</g>\n",
       "<!-- input__attempts&#45;&gt;creator -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>input__attempts&#45;&gt;creator</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M126.94,-295.92C128.12,-289.55 129.48,-282.16 130.78,-275.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"134.24,-275.66 132.61,-265.19 127.36,-274.39 134.24,-275.66\"/>\n",
       "</g>\n",
       "<!-- get_topic_feedback&#45;&gt;creator -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>get_topic_feedback&#45;&gt;creator</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M141.82,-198.19C142.45,-204.42 142.67,-211.63 142.47,-218.52\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"138.95,-218.72 141.81,-228.92 145.93,-219.16 138.95,-218.72\"/>\n",
       "</g>\n",
       "<!-- update_topics_so_far -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>update_topics_so_far</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M258.29,-117C258.29,-117 117.29,-117 117.29,-117 111.29,-117 105.29,-111 105.29,-105 105.29,-105 105.29,-93 105.29,-93 105.29,-87 111.29,-81 117.29,-81 117.29,-81 258.29,-81 258.29,-81 264.29,-81 270.29,-87 270.29,-93 270.29,-93 270.29,-105 270.29,-105 270.29,-111 264.29,-117 258.29,-117\"/>\n",
       "<text text-anchor=\"middle\" x=\"187.79\" y=\"-95.3\" font-family=\"Times,serif\" font-size=\"14.00\">update_topics_so_far</text>\n",
       "</g>\n",
       "<!-- get_topic_feedback&#45;&gt;update_topics_so_far -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>get_topic_feedback&#45;&gt;update_topics_so_far</title>\n",
       "<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M109.49,-161.93C99.3,-153.16 91.62,-142.19 98.79,-132 101.05,-128.79 103.66,-125.9 106.54,-123.3\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"108.89,-125.9 114.73,-117.06 104.65,-120.33 108.89,-125.9\"/>\n",
       "<text text-anchor=\"middle\" x=\"181.29\" y=\"-135.8\" font-family=\"Times,serif\" font-size=\"14.00\">topic_feedback is None</text>\n",
       "</g>\n",
       "<!-- update_topics_so_far&#45;&gt;creator -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>update_topics_so_far&#45;&gt;creator</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M248.53,-117.23C254.52,-121.18 259.83,-126.04 263.79,-132 267.48,-137.55 266.08,-140.74 263.79,-147 249.79,-185.31 210.51,-212 179.12,-227.94\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"177.54,-224.82 170.09,-232.35 180.61,-231.11 177.54,-224.82\"/>\n",
       "</g>\n",
       "<!-- terminal -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>terminal</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M214.29,-36C214.29,-36 161.29,-36 161.29,-36 155.29,-36 149.29,-30 149.29,-24 149.29,-24 149.29,-12 149.29,-12 149.29,-6 155.29,0 161.29,0 161.29,0 214.29,0 214.29,0 220.29,0 226.29,-6 226.29,-12 226.29,-12 226.29,-24 226.29,-24 226.29,-30 220.29,-36 214.29,-36\"/>\n",
       "<text text-anchor=\"middle\" x=\"187.79\" y=\"-14.3\" font-family=\"Times,serif\" font-size=\"14.00\">terminal</text>\n",
       "</g>\n",
       "<!-- update_topics_so_far&#45;&gt;terminal -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>update_topics_so_far&#45;&gt;terminal</title>\n",
       "<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M187.79,-80.86C187.79,-70.71 187.79,-57.63 187.79,-46.12\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"191.29,-46.11 187.79,-36.11 184.29,-46.11 191.29,-46.11\"/>\n",
       "<text text-anchor=\"middle\" x=\"341.29\" y=\"-54.8\" font-family=\"Times,serif\" font-size=\"14.00\">len(topics_so_far) == num_required_topics</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x7efca7259350>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app = topics_application()\n",
    "app.visualize(\n",
    "    output_file_path=\"statemachine\",\n",
    "    include_conditions=True,\n",
    "    include_state=False,\n",
    "    format=\"png\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's go through the visualization:\n",
    "1. Give the `ouline` string and the `num_required_topics` as inputs to `setup`.\n",
    "2. `creator` will run in a loop. Generated one topic at a time.\n",
    "3. If for whatever reason the `generated_topic` is None, this means there was some error even after some retries. In this case, `creator` will be called again.\n",
    "4. `get_topic_feedback` will be called to get feedback on `generated_topic`.\n",
    "5. If `topic_feedback` is None, it means that the user is satisfied. `update_topics_so_far` will be called to add the `generated_topic` to the `topics_so_far` list.\n",
    "6. If the user is not satisfied, `creator` will be called again with the `generated_topic` and `topic_feedback` added to the `chat_history`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "inputs = {\"outline\": \"history, science, math\", \"num_required_topics\": 3}\n",
    "\n",
    "while True:\n",
    "    action, result, state = app.run(halt_after=[\"terminal\"], inputs=inputs)\n",
    "    # let's stop after we have the required number of topics\n",
    "    if action.name == \"terminal\":\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Topic(name='History', subtopics=[Subtopic(name='Ancient Civilizations', concepts=['Analyze Ancient Empires', 'Compare Ancient Religions', 'Trace Historical Trade Routes', 'Study Ancient Writing Systems']), Subtopic(name='Medieval Period', concepts=['Explore Feudalism And Chivalry', 'Analyze The Rise Of Christianity', 'Study The Black Death And Its Impact', 'Examine The Crusades And Their Consequences']), Subtopic(name='Modern History', concepts=['Analyze The Renaissance And Reformation', 'Study The Age Of Exploration And Colonization', 'Examine The Industrial Revolution And Its Impact', 'Explore The World Wars And Their Aftermath'])]),\n",
       " Topic(name='Science', subtopics=[Subtopic(name='Biology', concepts=['Identify Cell Structures', 'Explain Photosynthesis', 'Analyze Dna Replication', 'Study Evolution And Adaptation']), Subtopic(name='Chemistry', concepts=['Understand Atomic Structure', 'Balance Chemical Equations', 'Calculate Molar Mass', 'Explore Chemical Reactions']), Subtopic(name='Physics', concepts=['Apply Laws Of Motion', 'Calculate Energy And Work', 'Understand Electricity And Magnetism', 'Explore Waves And Sound'])]),\n",
       " Topic(name='Math', subtopics=[Subtopic(name='Arithmetic And Algebra', concepts=['Perform Basic Arithmetic Operations', 'Solve Linear Equations', 'Simplify Algebraic Expressions', 'Factor Polynomials']), Subtopic(name='Geometry And Trigonometry', concepts=['Calculate Area And Perimeter', 'Identify Geometric Shapes', 'Apply Pythagorean Theorem', 'Solve For Volume And Surface Area']), Subtopic(name='Calculus And Statistics', concepts=['Find Derivatives Of Functions', 'Integrate Functions', 'Analyze Data Sets', 'Calculate Probability'])])]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app.state[\"topics_so_far\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'History',\n",
       " 'subtopics': [{'name': 'Ancient Civilizations',\n",
       "   'concepts': ['Analyze Ancient Empires',\n",
       "    'Compare Ancient Religions',\n",
       "    'Trace Historical Trade Routes',\n",
       "    'Study Ancient Writing Systems']},\n",
       "  {'name': 'Medieval Period',\n",
       "   'concepts': ['Explore Feudalism And Chivalry',\n",
       "    'Analyze The Rise Of Christianity',\n",
       "    'Study The Black Death And Its Impact',\n",
       "    'Examine The Crusades And Their Consequences']},\n",
       "  {'name': 'Modern History',\n",
       "   'concepts': ['Analyze The Renaissance And Reformation',\n",
       "    'Study The Age Of Exploration And Colonization',\n",
       "    'Examine The Industrial Revolution And Its Impact',\n",
       "    'Explore The World Wars And Their Aftermath']}]}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "topic1 = app.state[\"topics_so_far\"][0]\n",
    "topic1.model_dump()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'role': 'system',\n",
       "  'content': '\"You are a world class course instructor.\"\\nYou\\'ll be given a course outline and you have to generate 3 topics.\\nFor each topic:\\n    1. Generate a 3-5 word topic name that encapsulates the description.\\n    2. Generate 2-4 subtopics for the topic. Also 3-5 words each.\\n    For each subtopic:\\n        Generate 2-4 concepts. Also 3-5 words each. The concepts should be related to the subtopic.\\n        Think of concepts as the smallest unit of knowledge that can be taught from the subtopic. And add a verb to the concept to make it actionable.\\n        For example:\\n            \"Calculate Derivatives\" instead of \"Derivatives\".\\n            \"Identify Finite Sets\" instead of \"Finite Sets\".\\n            \"Find the y-intercept\" instead of \"y-intercept\".\\n    The subtopics and concepts should be in the correct order.'},\n",
       " {'role': 'user',\n",
       "  'content': '<outline>\\nhistory, science, math\\n</outline>\\n\\n<num_required_topics>\\n3\\n</num_required_topics>\\n\\n<topics_so_far>\\n</topics_so_far>\\n\\nGenerate the next topic.'},\n",
       " {'role': 'assistant',\n",
       "  'content': 'TOPIC: Mathematics\\nSUBTOPIC 1: Algebraic Foundations\\nCONCEPT 1: Simplify Algebraic Expressions\\nCONCEPT 2: Solve Linear Equations\\nCONCEPT 3: Factor Polynomials\\nCONCEPT 4: Graph Linear Functions\\nSUBTOPIC 2: Geometric Concepts\\nCONCEPT 1: Calculate Area And Perimeter\\nCONCEPT 2: Identify Geometric Shapes\\nCONCEPT 3: Apply Pythagorean Theorem\\nCONCEPT 4: Solve For Volume And Surface Area\\nSUBTOPIC 3: Trigonometry And Calculus\\nCONCEPT 1: Calculate Sine, Cosine, And Tangent\\nCONCEPT 2: Solve Trigonometric Equations\\nCONCEPT 3: Find Derivatives Of Functions\\nCONCEPT 4: Integrate Functions\\n'},\n",
       " {'role': 'user',\n",
       "  'content': 'User feedback: I want the topics to be in the same sequence as the outline'},\n",
       " {'role': 'assistant',\n",
       "  'content': 'TOPIC: History\\nSUBTOPIC 1: Ancient Civilizations\\nCONCEPT 1: Analyze Ancient Empires\\nCONCEPT 2: Compare Ancient Religions\\nCONCEPT 3: Trace Historical Trade Routes\\nCONCEPT 4: Study Ancient Writing Systems\\nSUBTOPIC 2: Medieval Period\\nCONCEPT 1: Explore Feudalism And Chivalry\\nCONCEPT 2: Analyze The Rise Of Christianity\\nCONCEPT 3: Study The Black Death And Its Impact\\nCONCEPT 4: Examine The Crusades And Their Consequences\\nSUBTOPIC 3: Modern History\\nCONCEPT 1: Analyze The Renaissance And Reformation\\nCONCEPT 2: Study The Age Of Exploration And Colonization\\nCONCEPT 3: Examine The Industrial Revolution And Its Impact\\nCONCEPT 4: Explore The World Wars And Their Aftermath\\n'},\n",
       " {'role': 'user',\n",
       "  'content': '<outline>\\nhistory, science, math\\n</outline>\\n\\n<num_required_topics>\\n3\\n</num_required_topics>\\n\\n<topics_so_far>\\n1/3\\nTOPIC: History\\nSUBTOPIC 1: Ancient Civilizations\\nCONCEPT 1: Analyze Ancient Empires\\nCONCEPT 2: Compare Ancient Religions\\nCONCEPT 3: Trace Historical Trade Routes\\nCONCEPT 4: Study Ancient Writing Systems\\nSUBTOPIC 2: Medieval Period\\nCONCEPT 1: Explore Feudalism And Chivalry\\nCONCEPT 2: Analyze The Rise Of Christianity\\nCONCEPT 3: Study The Black Death And Its Impact\\nCONCEPT 4: Examine The Crusades And Their Consequences\\nSUBTOPIC 3: Modern History\\nCONCEPT 1: Analyze The Renaissance And Reformation\\nCONCEPT 2: Study The Age Of Exploration And Colonization\\nCONCEPT 3: Examine The Industrial Revolution And Its Impact\\nCONCEPT 4: Explore The World Wars And Their Aftermath\\n</topics_so_far>\\n\\nGenerate the next topic.'},\n",
       " {'role': 'assistant',\n",
       "  'content': 'TOPIC: Science\\nSUBTOPIC 1: Biology\\nCONCEPT 1: Identify Cell Structures\\nCONCEPT 2: Explain Photosynthesis\\nCONCEPT 3: Analyze Dna Replication\\nCONCEPT 4: Study Evolution And Adaptation\\nSUBTOPIC 2: Chemistry\\nCONCEPT 1: Understand Atomic Structure\\nCONCEPT 2: Balance Chemical Equations\\nCONCEPT 3: Calculate Molar Mass\\nCONCEPT 4: Explore Chemical Reactions\\nSUBTOPIC 3: Physics\\nCONCEPT 1: Apply Laws Of Motion\\nCONCEPT 2: Calculate Energy And Work\\nCONCEPT 3: Understand Electricity And Magnetism\\nCONCEPT 4: Explore Waves And Sound\\n'},\n",
       " {'role': 'user',\n",
       "  'content': '<outline>\\nhistory, science, math\\n</outline>\\n\\n<num_required_topics>\\n3\\n</num_required_topics>\\n\\n<topics_so_far>\\n1/3\\nTOPIC: History\\nSUBTOPIC 1: Ancient Civilizations\\nCONCEPT 1: Analyze Ancient Empires\\nCONCEPT 2: Compare Ancient Religions\\nCONCEPT 3: Trace Historical Trade Routes\\nCONCEPT 4: Study Ancient Writing Systems\\nSUBTOPIC 2: Medieval Period\\nCONCEPT 1: Explore Feudalism And Chivalry\\nCONCEPT 2: Analyze The Rise Of Christianity\\nCONCEPT 3: Study The Black Death And Its Impact\\nCONCEPT 4: Examine The Crusades And Their Consequences\\nSUBTOPIC 3: Modern History\\nCONCEPT 1: Analyze The Renaissance And Reformation\\nCONCEPT 2: Study The Age Of Exploration And Colonization\\nCONCEPT 3: Examine The Industrial Revolution And Its Impact\\nCONCEPT 4: Explore The World Wars And Their Aftermath\\n\\n2/3\\nTOPIC: Science\\nSUBTOPIC 1: Biology\\nCONCEPT 1: Identify Cell Structures\\nCONCEPT 2: Explain Photosynthesis\\nCONCEPT 3: Analyze Dna Replication\\nCONCEPT 4: Study Evolution And Adaptation\\nSUBTOPIC 2: Chemistry\\nCONCEPT 1: Understand Atomic Structure\\nCONCEPT 2: Balance Chemical Equations\\nCONCEPT 3: Calculate Molar Mass\\nCONCEPT 4: Explore Chemical Reactions\\nSUBTOPIC 3: Physics\\nCONCEPT 1: Apply Laws Of Motion\\nCONCEPT 2: Calculate Energy And Work\\nCONCEPT 3: Understand Electricity And Magnetism\\nCONCEPT 4: Explore Waves And Sound\\n</topics_so_far>\\n\\nGenerate the next topic.'},\n",
       " {'role': 'assistant',\n",
       "  'content': 'TOPIC: Math\\nSUBTOPIC 1: Arithmetic And Algebra\\nCONCEPT 1: Perform Basic Arithmetic Operations\\nCONCEPT 2: Solve Linear Equations\\nCONCEPT 3: Simplify Algebraic Expressions\\nCONCEPT 4: Factor Polynomials\\nSUBTOPIC 2: Geometry And Trigonometry\\nCONCEPT 1: Calculate Area And Perimeter\\nCONCEPT 2: Identify Geometric Shapes\\nCONCEPT 3: Apply Pythagorean Theorem\\nCONCEPT 4: Solve For Volume And Surface Area\\nSUBTOPIC 3: Calculus And Statistics\\nCONCEPT 1: Find Derivatives Of Functions\\nCONCEPT 2: Integrate Functions\\nCONCEPT 3: Analyze Data Sets\\nCONCEPT 4: Calculate Probability\\n'}]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app.state[\"chat_history\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
